﻿using Microsoft.Extensions.Logging;
using Quartz;

namespace Simple.Services.Jobs
{
    [DisallowConcurrentExecution]
    public class NoticeSendJob : IJob
    {

        private readonly ILogger<NoticeSendJob> _logger;
        private readonly CacheService _cacheService;
        private readonly SemaphoreSlim _jobLock = new SemaphoreSlim(1, 1);
        private readonly UserService _userService;
        private readonly SimpleDbContext _dbContext;
        private readonly ChildrenService _childrenService;
        public NoticeSendJob(ILogger<NoticeSendJob> logger, CacheService cacheService, UserService userService, SimpleDbContext dbContext, ChildrenService childrenService)
        {
            _logger = logger;
            _cacheService = cacheService;
            _userService = userService;
            _dbContext = dbContext;
            _childrenService = childrenService;
        }

        public async Task Execute(IJobExecutionContext context)
        {
            try
            {
                var sysNotices = new List<SysNotice>();
                _jobLock.Wait();
                var notices = await _cacheService.GetCacheItemsByPrefixAsync<SysNotice>(CacheKeyConst.NoticeMessage);
                int executeCount = 0;
                if (notices != null && notices.Any())
                {
                    var executeNotices = notices.Where(s => s.SendTime <= DateTime.Now && s.IsSend == false).ToList();
                    if (executeNotices.Any())
                    {
                        executeCount = executeNotices.Count;
                        var sendTime = DateTime.Now;
                        foreach (var notice in executeNotices)
                        {
                            notice.IsSend = true;
                            notice.UpdatedTime = sendTime;
                            notice.UpdatedUserId = notice.CreatedUserId;
                            if (notice.DepartmentId.HasValue)
                            {
                                var orgUsers = await _userService.GetUsersByOrgTreeAsync(notice.DepartmentId.Value);
                                if (orgUsers != null && orgUsers.Any())
                                {
                                    foreach(var user in orgUsers)
                                    {
                                        sysNotices.Add(new SysNotice
                                        {
                                            IsOriginal = false,
                                            Content = notice.Content,
                                            ClassId = notice.ClassId,
                                            IsSend = true,
                                            DepartmentId = notice.DepartmentId,
                                            IsRead =false,
                                            Title= notice.Title,
                                            Receiver = user.Id,
                                            ReceivingPort = 0,
                                            SendTime = sendTime,
                                            SendUserName = notice.SendUserName,
                                            CreatedUserId = notice.CreatedUserId,
                                            CreatedTime = sendTime,
                                            Url = notice.Url
                                        });
                                    }
                                }

                            }
                            if (notice.ClassId != null )
                            {
                                var classUsers = await _childrenService.GetParentByClassIdAsync(notice.ClassId.Value);
                                if (classUsers != null && classUsers.Any())
                                {
                                    foreach (var user in classUsers)
                                    {
                                        sysNotices.Add(new SysNotice
                                        {
                                            IsOriginal = false,
                                            Content = notice.Content,
                                            ClassId = notice.ClassId,
                                            IsSend = true,
                                            DepartmentId = notice.DepartmentId,
                                            IsRead = false,
                                            Title = notice.Title,
                                            Receiver = user.Id,
                                            ReceivingPort = 1,
                                            SendTime = sendTime,
                                            SendUserName = notice.SendUserName,
                                            CreatedUserId = notice.CreatedUserId,
                                            CreatedTime = sendTime,
                                            Url = notice.Url
                                        });
                                    }
                                }
                            }
                             _dbContext.UpdateRange(executeNotices);
                        }

                        var cacheKeys = executeNotices.Select(s => _cacheService.GetKey(CacheKeyConst.NoticeMessage, s.Id.ToString())).ToArray();
                        await _cacheService.RemoveRangeAsync(cacheKeys);
                    }
                }
                if(sysNotices.Any())
                {
                    await _dbContext.AddRangeAsync(sysNotices);
                    _logger.LogInformation($"NoticeSendJob 执行完毕，共执行{executeCount}条!");
                }
                await _dbContext.SaveChangesAsync();
                _jobLock.Release();
            }
            catch (Exception ex)
            {
                _logger.LogError($"NoticeSendJob执行发生错误: {ex.Message}");
            }
        }
    }
}
